﻿namespace Smart.Utils.Localization
{
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.ComponentModel.Design;
    using System.Drawing;
    using System.Drawing.Design;
    using System.Globalization;
    using System.Reflection;
    using System.Resources;
    using System.Runtime.CompilerServices;
    using System.Threading;
    using System.Windows.Forms;

    [ToolboxItem(true)]
    public class CultureManager : Component
    {
        private static CultureInfo _applicationUICulture;
        private List<string> _excludeProperties;
        private Control _managedControl;
        private bool _preserveFormLocation;
        private bool _preserveFormSize;
        private static bool _synchronizeThreadCulture = true;
        private bool _synchronizeUICulture;
        private CultureInfo _uiCulture;
        private const AnchorStyles anchorAll = (AnchorStyles.Right | AnchorStyles.Left | AnchorStyles.Bottom | AnchorStyles.Top);
        private const AnchorStyles anchorLeftRight = (AnchorStyles.Right | AnchorStyles.Left);
        private const AnchorStyles anchorTopBottom = (AnchorStyles.Bottom | AnchorStyles.Top);

        public static  event CultureChangedHandler ApplicationUICultureChanged;

        public event CultureChangedHandler UICultureChanged;

        public CultureManager()
        {
            this._preserveFormSize = true;
            this._preserveFormLocation = true;
            this._excludeProperties = new List<string>();
            this._synchronizeUICulture = true;
            ApplicationUICultureChanged = (CultureChangedHandler) Delegate.Combine(ApplicationUICultureChanged, new CultureChangedHandler(this.OnApplicationUICultureChanged));
        }

        public CultureManager(IContainer container) : this()
        {
            container.Add(this);
        }

        protected virtual void ApplyExtenderResource(Dictionary<System.Type, IExtenderProvider> extenderProviders, Control control, string propertyName, object value)
        {
            IExtenderProvider provider = null;
            if (propertyName == "ToolTip")
            {
                if (extenderProviders.TryGetValue(typeof(ToolTip), out provider))
                {
                    (provider as ToolTip).SetToolTip(control, value as string);
                }
            }
            else if (propertyName == "HelpKeyword")
            {
                if (extenderProviders.TryGetValue(typeof(HelpProvider), out provider))
                {
                    (provider as HelpProvider).SetHelpKeyword(control, value as string);
                }
            }
            else if (propertyName == "HelpString")
            {
                if (extenderProviders.TryGetValue(typeof(HelpProvider), out provider))
                {
                    (provider as HelpProvider).SetHelpString(control, value as string);
                }
            }
            else if (propertyName == "ShowHelp")
            {
                if (extenderProviders.TryGetValue(typeof(HelpProvider), out provider))
                {
                    (provider as HelpProvider).SetShowHelp(control, (bool) value);
                }
            }
            else if (propertyName == "Error")
            {
                if (extenderProviders.TryGetValue(typeof(ErrorProvider), out provider))
                {
                    (provider as ErrorProvider).SetError(control, value as string);
                }
            }
            else if (propertyName == "IconAlignment")
            {
                if (extenderProviders.TryGetValue(typeof(ErrorProvider), out provider))
                {
                    (provider as ErrorProvider).SetIconAlignment(control, (ErrorIconAlignment) value);
                }
            }
            else if ((propertyName == "IconPadding") && extenderProviders.TryGetValue(typeof(ErrorProvider), out provider))
            {
                (provider as ErrorProvider).SetIconPadding(control, (int) value);
            }
        }

        protected virtual void ApplyResources(System.Type componentType, IComponent instance, CultureInfo culture)
        {
            if (componentType.Assembly.GetManifestResourceStream(componentType.FullName + ".resources") != null)
            {
                string key;
                System.Type baseType = componentType.BaseType;
                if (baseType != null)
                {
                    this.ApplyResources(baseType, instance, culture);
                }
                ComponentResourceManager rm = new ComponentResourceManager(componentType);
                SortedList<string, object> resources = new SortedList<string, object>();
                this.LoadResources(rm, culture, resources);
                Dictionary<string, IComponent> dictionary = new Dictionary<string, IComponent>();
                Dictionary<System.Type, IExtenderProvider> extenderProviders = new Dictionary<System.Type, IExtenderProvider>();
                bool flag = IsVBAssembly(componentType.Assembly);
                dictionary["$this"] = instance;
                FieldInfo[] fields = componentType.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
                foreach (FieldInfo info in fields)
                {
                    string name = info.Name;
                    if (flag)
                    {
                        name = name.Substring(1, name.Length - 1);
                    }
                    key = ">>" + name + ".Name";
                    if (resources.ContainsKey(key))
                    {
                        IComponent component = info.GetValue(instance) as IComponent;
                        if (component != null)
                        {
                            dictionary[name] = component;
                            this.ApplyResources(component.GetType(), component, culture);
                            if (component is IExtenderProvider)
                            {
                                extenderProviders[component.GetType()] = component as IExtenderProvider;
                            }
                        }
                    }
                }
                foreach (KeyValuePair<string, object> pair in resources)
                {
                    IComponent component2;
                    Control control;
                    PropertyDescriptor descriptor;
                    key = pair.Key;
                    object o = pair.Value;
                    string[] strArray = key.Split(new char[] { '.' });
                    string str3 = strArray[0];
                    string item = strArray[1];
                    if (!str3.StartsWith(">>") && !this._excludeProperties.Contains(item))
                    {
                        component2 = null;
                        if (dictionary.TryGetValue(str3, out component2))
                        {
                            control = component2 as Control;
                            if (control == null)
                            {
                                goto Label_02A6;
                            }
                            string str5 = item;
                            if (str5 == null)
                            {
                                goto Label_02A6;
                            }
                            if (!(str5 == "Size"))
                            {
                                if (str5 == "Location")
                                {
                                    goto Label_0271;
                                }
                                if (str5 == "ClientSize")
                                {
                                    goto Label_0286;
                                }
                                goto Label_02A6;
                            }
                            this.SetControlSize(control, (Size) o);
                        }
                    }
                    continue;
                Label_0271:
                    this.SetControlLocation(control, (Point) o);
                    continue;
                Label_0286:
                    if ((control is Form) && this.PreserveFormSize)
                    {
                        continue;
                    }
                Label_02A6:
                    descriptor = TypeDescriptor.GetProperties(component2).Find(item, false);
                    if (((descriptor != null) && !descriptor.IsReadOnly) && ((o == null) || descriptor.PropertyType.IsInstanceOfType(o)))
                    {
                        descriptor.SetValue(component2, o);
                    }
                    else if (control != null)
                    {
                        this.ApplyExtenderResource(extenderProviders, control, item, o);
                    }
                }
            }
        }

        protected virtual void ChangeUICulture(CultureInfo culture)
        {
            if (!culture.Equals(this._uiCulture))
            {
                this._uiCulture = culture;
                if (this._managedControl != null)
                {
                    this._managedControl.SuspendLayout();
                    foreach (Control control in this._managedControl.Controls)
                    {
                        control.SuspendLayout();
                    }
                    try
                    {
                        this.ApplyResources(this._managedControl.GetType(), this._managedControl, culture);
                        this.OnUICultureChanged(culture);
                    }
                    finally
                    {
                        foreach (Control control in this._managedControl.Controls)
                        {
                            control.ResumeLayout();
                        }
                        this._managedControl.ResumeLayout();
                    }
                }
            }
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                ApplicationUICultureChanged = (CultureChangedHandler) Delegate.Remove(ApplicationUICultureChanged, new CultureChangedHandler(this.OnApplicationUICultureChanged));
            }
            base.Dispose(disposing);
        }

        protected static bool IsVBAssembly(Assembly assembly)
        {
            AssemblyName[] referencedAssemblies = assembly.GetReferencedAssemblies();
            foreach (AssemblyName name in referencedAssemblies)
            {
                if (name.Name == "Microsoft.VisualBasic")
                {
                    return true;
                }
            }
            return false;
        }

        private void LoadResources(ComponentResourceManager rm, CultureInfo culture, SortedList<string, object> resources)
        {
            if (!culture.Equals(CultureInfo.InvariantCulture))
            {
                this.LoadResources(rm, culture.Parent, resources);
            }
            ResourceSet set = rm.GetResourceSet(culture, true, true);
            if (set != null)
            {
                foreach (DictionaryEntry entry in set)
                {
                    resources[(string) entry.Key] = entry.Value;
                }
            }
        }

        protected virtual void OnApplicationUICultureChanged(CultureInfo newCulture)
        {
            if (this.SynchronizeUICulture)
            {
                this.ChangeUICulture(newCulture);
            }
        }

        protected virtual void OnUICultureChanged(CultureInfo newCulture)
        {
            if (this.UICultureChanged != null)
            {
                this.UICultureChanged(newCulture);
            }
        }

        private void ResetExcludeProperties()
        {
            this._excludeProperties.Clear();
        }

        protected virtual void SetControlLocation(Control control, Point location)
        {
            if ((!(control is Form) || !this.PreserveFormLocation) && (control.Dock == DockStyle.None))
            {
                if ((control.Anchor & (AnchorStyles.Right | AnchorStyles.Left)) == AnchorStyles.Right)
                {
                    location.X = control.Left;
                }
                if ((control.Anchor & (AnchorStyles.Bottom | AnchorStyles.Top)) == AnchorStyles.Bottom)
                {
                    location.Y = control.Top;
                }
                control.Location = location;
            }
        }

        protected virtual void SetControlSize(Control control, Size size)
        {
            if ((!(control is Form) || !this.PreserveFormSize) && ((control.Dock != DockStyle.Fill) && (control.Anchor != (AnchorStyles.Right | AnchorStyles.Left | AnchorStyles.Bottom | AnchorStyles.Top))))
            {
                if (((control.Dock == DockStyle.Top) || (control.Dock == DockStyle.Bottom)) || ((control.Anchor & (AnchorStyles.Right | AnchorStyles.Left)) == (AnchorStyles.Right | AnchorStyles.Left)))
                {
                    size.Width = control.Width;
                }
                if (((control.Dock == DockStyle.Left) || (control.Dock == DockStyle.Right)) || ((control.Anchor & (AnchorStyles.Bottom | AnchorStyles.Top)) == (AnchorStyles.Bottom | AnchorStyles.Top)))
                {
                    size.Height = control.Height;
                }
                control.Size = size;
            }
        }

        private static void SetThreadCulture(CultureInfo value)
        {
            if (value.IsNeutralCulture)
            {
                Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(value.Name);
            }
            else
            {
                Thread.CurrentThread.CurrentCulture = value;
            }
        }

        public static void SetThreadUICulture(bool synchronizeThreadCulture)
        {
            Thread.CurrentThread.CurrentUICulture = ApplicationUICulture;
            if (synchronizeThreadCulture)
            {
                if (ApplicationUICulture.IsNeutralCulture)
                {
                    Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(ApplicationUICulture.Name);
                }
                else
                {
                    Thread.CurrentThread.CurrentCulture = ApplicationUICulture;
                }
            }
        }

        private bool ShouldSerializeExcludeProperties()
        {
            return (this._excludeProperties.Count > 0);
        }

        public static CultureInfo ApplicationUICulture
        {
            get
            {
                if (_applicationUICulture == null)
                {
                    _applicationUICulture = Thread.CurrentThread.CurrentUICulture;
                }
                return _applicationUICulture;
            }
            set
            {
                if (value == null)
                {
                    throw new ArgumentNullException();
                }
                if (!value.Equals(_applicationUICulture))
                {
                    _applicationUICulture = value;
                    SetThreadUICulture(SynchronizeThreadCulture);
                    if (ApplicationUICultureChanged != null)
                    {
                        ApplicationUICultureChanged(value);
                    }
                }
            }
        }

        [Editor("System.Windows.Forms.Design.StringCollectionEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof(UITypeEditor)), Description("List of properties to exclude when applying culture specific resources"), DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public List<string> ExcludeProperties
        {
            get
            {
                return this._excludeProperties;
            }
            set
            {
                if (value == null)
                {
                    throw new ArgumentNullException();
                }
                this._excludeProperties = value;
            }
        }

        [Description("The control or form to manage the UICulture for")]
        public Control ManagedControl
        {
            get
            {
                if ((this._managedControl == null) && (this.Site != null))
                {
                    IDesignerHost service = this.Site.GetService(typeof(IDesignerHost)) as IDesignerHost;
                    if (((service != null) && (service.Container != null)) && (service.Container.Components.Count > 0))
                    {
                        this._managedControl = service.Container.Components[0] as Control;
                    }
                }
                return this._managedControl;
            }
            set
            {
                this._managedControl = value;
            }
        }

        [Description("Should the form location be preserved when the culture is changed"), DefaultValue(true)]
        public bool PreserveFormLocation
        {
            get
            {
                return this._preserveFormLocation;
            }
            set
            {
                this._preserveFormLocation = value;
            }
        }

        [DefaultValue(true), Description("Should the form size be preserved when the culture is changed")]
        public bool PreserveFormSize
        {
            get
            {
                return this._preserveFormSize;
            }
            set
            {
                this._preserveFormSize = value;
            }
        }

        public static bool SynchronizeThreadCulture
        {
            get
            {
                return _synchronizeThreadCulture;
            }
            set
            {
                _synchronizeThreadCulture = value;
                if (value)
                {
                    SetThreadUICulture(true);
                }
            }
        }

        [Description("Should the UICulture of this form be changed when the ApplicationUICulture"), DefaultValue(true)]
        public bool SynchronizeUICulture
        {
            get
            {
                return this._synchronizeUICulture;
            }
            set
            {
                this._synchronizeUICulture = value;
            }
        }

        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), Browsable(false)]
        public CultureInfo UICulture
        {
            get
            {
                if (this._uiCulture == null)
                {
                    this._uiCulture = ApplicationUICulture;
                }
                return this._uiCulture;
            }
            set
            {
                if (value == null)
                {
                    throw new ArgumentNullException();
                }
                this.ChangeUICulture(value);
            }
        }

        public delegate void CultureChangedHandler(CultureInfo newCulture);
    }
}

